package com.ruoyi.businessOrder.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import com.ruoyi.common.utils.StringUtils;

import cn.elegent.pay.ElegentPay;
import cn.elegent.pay.dto.*;
import cn.elegent.pay.dto.PayResponse;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.ruoyi.businessOrder.domain.dto.BusinessOrderDto;
import com.ruoyi.businessOrder.domain.dto.RefundApplyDto;
import com.ruoyi.businessOrder.domain.dto.RefundAuditDto;
import com.ruoyi.common.config.WxPaymentConfig;
import com.ruoyi.common.exception.ServiceException;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.businessOrder.domain.BusinessOrder;
import com.ruoyi.businessOrder.service.IBusinessOrderService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;

/**
 * 交易订单信息Controller
 * 
 * @author ruoyi
 * @date 2025-06-11
 */
@RestController
@RequestMapping("/ruoyi/businessOrder")
@Slf4j
public class BusinessOrderController extends BaseController
{
    @Autowired
    private IBusinessOrderService businessOrderService;

    @Autowired
    private ElegentPay elegentPay;

    @Autowired
    private WxPaymentConfig wxPaymentConfig;

    /**
     * 调用统一下单API,获取预支付ID
     */
    @ApiOperation("统一下单测试接口")
    @PostMapping("/jsapi/{orderId}")
    public AjaxResult miniAppGetPrePayId(@PathVariable("orderId") Long orderId) throws Exception {
        log.info("发起支付请求");
        // 返回预支付ID
        HashMap<String, Object> map = businessOrderService.miniAppGetPrePayId(orderId);

        return success(map);
    }

    /**
     * 通过JSAPI/小程序下单接口获取到发起支付的必要参数prepay_id,构造签名
     */
    @ApiOperation("JSAPI/小程序下单接口")
    @PostMapping("/getWxpayParams")
    public AjaxResult getWxpayParams(@RequestBody Map<String, Object> params) throws Exception {
        try {
            // 1. 解析并校验 orderId
            Object orderIdObj = params.get("orderId");
            if (orderIdObj == null) {
                return AjaxResult.error("参数缺失（orderId必须为数字）");
            }
            Long orderId;
            try {
                if (orderIdObj instanceof Number) {
                    orderId = ((Number) orderIdObj).longValue();
                } else {
                    orderId = Long.valueOf(orderIdObj.toString());
                }
            } catch (NumberFormatException e) {
                return AjaxResult.error("orderId必须为数字");
            }

            // 订单id
//            Long orderId = (Long) params.get("orderId");
            // 订单号
            String orderNo = (String) params.get("orderNo");
            // 微信openId
            String openId = (String) params.get("openId");

            Integer totalFee;
            try {
                // 将金额字符串转换为BigDecimal
                BigDecimal amount = new BigDecimal(params.get("totalFee").toString());

                // 验证金额有效性
                if (amount.compareTo(BigDecimal.ZERO) <= 0) {
                    return AjaxResult.error("支付金额必须大于0");
                }
                // 元转分（乘以100后取整）
                totalFee = amount.multiply(new BigDecimal("100")).intValueExact();

            } catch (NumberFormatException | ArithmeticException e) {
                return AjaxResult.error("支付金额格式错误，示例：0.01");
            } catch (NullPointerException e) {
                return AjaxResult.error("未提供支付金额");
            }

            // 2. 校验参数完整性
            if (orderId == null || orderNo == null || totalFee == null || openId == null) {
                return AjaxResult.error("参数缺失（orderId、orderNo、totalFee、openId均为必填）");
            }

            Map<String, String> payParams = businessOrderService.getWxpayParams(orderId, orderNo, totalFee, openId);

            // 4. 返回成功结果（包含支付参数）
            return AjaxResult.success("获取支付参数成功", payParams);

        } catch (Exception e) {
            // 5. 返回失败结果（包含错误信息）
            return AjaxResult.error("获取支付参数失败：" + e.getMessage());
        }

    }

    /**
     * 关闭订单
     */
    @ApiOperation("关闭订单")
    @PostMapping("/miniAppCloseOrder/{orderId}")
    public AjaxResult miniAppCloseOrder(@PathVariable("orderId") Long orderId) throws Exception {
        log.info("关闭订单");
        // 返回预支付ID
        HashMap<String, Object> map = businessOrderService.miniAppCloseOrder(orderId);

        return success(map);
    }

    /**
     * 微信支付回调
     */
    @PostMapping("/miniAppNotify")
    public AjaxResult miniAppNotify(HttpServletRequest request, HttpServletResponse response) {
        try {
            log.info("接收到微信支付回调通知");

            // 1. 读取回调数据
            String notifyData = readNotifyData(request);
            if (StringUtils.isEmpty(notifyData)) {
                log.error("支付回调数据为空");
                return AjaxResult.error("回调数据为空");
            }

            // 2. 解析回调数据
            Map<String, String> notifyMap = parseNotifyData(notifyData);
            if (notifyMap == null) {
                log.error("支付回调数据解析失败");
                return AjaxResult.error("回调数据解析失败");
            }

            // 3. 验证签名
            if (!verifySignature(notifyMap)) {
                log.error("支付回调签名验证失败");
                return AjaxResult.error("签名验证失败");
            }

            // 4. 获取订单信息
            String orderCode = notifyMap.get("out_trade_no");
            String tradeState = notifyMap.get("trade_state");

            if (!"SUCCESS".equals(tradeState)) {
                log.info("支付未成功，交易状态: {}", tradeState);
                return AjaxResult.success("支付未成功");
            }

            // 5. 根据订单号查询订单ID
            BusinessOrder order = businessOrderService.getByOrderCode(orderCode);
            if (order == null) {
                log.error("订单不存在，订单编号: {}", orderCode);
                return AjaxResult.error("订单不存在");
            }

            // 6. 处理支付成功逻辑
//            businessOrderService.handlePaymentSuccess(order.getOrderId());

            log.info("支付回调处理成功，订单ID: {}", order.getOrderId());

            // 7. 返回成功响应给微信
            response.setContentType("application/xml;charset=utf-8");
            response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK</return_msg></xml>");

            return null; // 已经直接写入响应，返回null
        } catch (Exception e) {
            log.error("处理微信支付回调时发生异常", e);
            try {
                // 返回失败响应给微信
                response.setContentType("application/xml;charset=utf-8");
                response.getWriter().write("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[处理失败</return_msg></xml>");
            } catch (IOException ioException) {
                log.error("写入失败响应时发生异常", ioException);
            }
            return AjaxResult.error("处理支付回调失败");
        }
    }

    /**
     * 读取回调数据
     */
    private String readNotifyData(HttpServletRequest request) throws IOException {
        StringBuilder sb = new StringBuilder();
        try (BufferedReader reader = request.getReader()) {
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        }
        return sb.toString();
    }

    /**
     * 解析回调数据
     */
    private Map<String, String> parseNotifyData(String notifyData) {
        try {
            // 微信支付回调数据是XML格式
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(new InputSource(new StringReader(notifyData)));

            NodeList nodeList = document.getDocumentElement().getChildNodes();
            Map<String, String> result = new HashMap<>();

            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    result.put(node.getNodeName(), node.getTextContent());
                }
            }

            return result;
        } catch (Exception e) {
            log.error("解析支付回调数据失败", e);
            return null;
        }
    }

    /**
     * 验证签名
     */
    private boolean verifySignature(Map<String, String> notifyMap) {
        try {
            // 这里需要实现微信支付签名验证逻辑
            // 由于签名验证涉及商户密钥等敏感信息，这里简化处理
            // 实际项目中应该严格按照微信支付文档实现签名验证
            String sign = notifyMap.get("sign");
            if (StringUtils.isEmpty(sign)) {
                log.error("签名参数为空");
                return false;
            }

            // TODO: 实现完整的签名验证逻辑
            // 这里暂时返回true，实际项目中需要严格验证
            return true;
        } catch (Exception e) {
            log.error("验证签名时发生异常", e);
            return false;
        }
    }

    /**
     * 提交退款申请（用户端）
     */
    @ApiOperation("提交退款申请")
    @PostMapping("/submitRefundApply")
    public AjaxResult submitRefundApply(@RequestBody RefundApplyDto refundApplyDto) {
        try {
            businessOrderService.applyRefund(refundApplyDto);
            return AjaxResult.success("退款申请已提交，等待管理员审核");
        } catch (ServiceException e) {
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            log.error("提交退款申请失败", e);
            return AjaxResult.error("系统异常，请稍后重试");
        }
    }

    /**
     * 审核退款申请（管理端）
     */
    @ApiOperation("审核退款申请")
//    @PreAuthorize("@ss.hasPermi('refund:application:audit')")
    @PutMapping("/auditRefundApplication/{refundId}")
    public AjaxResult auditRefundApplication(
            @PathVariable("refundId") Long refundId,
            @RequestBody RefundAuditDto auditDto) {
        try {
            // 验证审核状态是否合法
            if (!"1".equals(auditDto.getAuditStatus()) && !"2".equals(auditDto.getAuditStatus())) {
                return AjaxResult.error("审核状态不合法");
            }

            businessOrderService.auditRefundApplication(refundId, auditDto);
            return AjaxResult.success("审核操作成功");
        } catch (ServiceException e) {
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            log.error("审核退款申请失败", e);
            return AjaxResult.error("系统异常，请稍后重试");
        }
    }

    /**
     * 退款申请
     */
    @ApiOperation("退款申请")
    @PostMapping("/miniAppRefund/{orderId}/{reason}")
    public AjaxResult miniAppRefund(@PathVariable("orderId") Long orderId,
                                    @PathVariable("reason") String reason) throws Exception{
        log.info("退款申请");
        try {
            HashMap<String, Object> map = businessOrderService.miniAppRefund(orderId,  reason);
            return AjaxResult.success("退款申请成功", map);
        } catch (ServiceException e) {
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            log.error("退款处理异常", e);
            return AjaxResult.error("系统异常，请稍后重试");
        }
    }

    /**
     * 支付
     */
    @PostMapping("/requestPay/{tradeType}/{platform}")
    public PayResponse requestpay(@RequestBody BusinessOrderDto payDto,
                                  @PathVariable("tradeType") String tradeType,
                                  @PathVariable("platform") String platform) {

         //1、创建订单
        BusinessOrder order = businessOrderService.createOrder(payDto, platform);//创建订单//2，调用支付
        PayRequest param = new PayRequest();
        param.setBody(order.getBusinessName()); //订单名称
        param.setOrderSn(order.getOrderCode()); //订单编号
        param.setTotalFee(order.getAmount().intValue()); //订单金额
        // param.setOpenid(order.getOpenId()); //openid

        return elegentPay.requestPay(param, tradeType, platform);
    }

    /**
     * 获取业务订单列表时，将订单状态为'3'（退款中）的优先级设为最高，排在最前面
     * 获取交易订单汇总列表
     */
    @GetMapping("/selectBusinessOrderSummaryList")
    public TableDataInfo selectBusinessOrderSummaryList(BusinessOrder businessOrder) {
        startPage();
        List<BusinessOrder> list = businessOrderService.selectBusinessOrderSummaryList(businessOrder);
        return getDataTable(list);
    }

    /**
     * 查询交易订单信息列表
     */
    // @PreAuthorize("@ss.hasPermi('ruoyi:businessOrder:list')")
    @GetMapping("/list")
    public TableDataInfo list(BusinessOrder businessOrder)
    {
        startPage();
        List<BusinessOrder> list = businessOrderService.selectBusinessOrderList(businessOrder);
        return getDataTable(list);
    }

    /**
     * 导出交易订单信息列表
     */
    // @PreAuthorize("@ss.hasPermi('ruoyi:businessOrder:export')")
    @Log(title = "交易订单信息", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, BusinessOrder businessOrder)
    {
        List<BusinessOrder> list = businessOrderService.selectBusinessOrderList(businessOrder);
        ExcelUtil<BusinessOrder> util = new ExcelUtil<BusinessOrder>(BusinessOrder.class);
        util.exportExcel(response, list, "交易订单信息数据");
    }

    /**
     * 获取交易订单信息详细信息
     */
    // @PreAuthorize("@ss.hasPermi('ruoyi:businessOrder:query')")
    @GetMapping(value = "/{orderId}")
    public AjaxResult getInfo(@PathVariable("orderId") Long orderId)
    {
        return success(businessOrderService.selectBusinessOrderByOrderId(orderId));
    }

    /**
     * 新增交易订单信息
     */
    // @PreAuthorize("@ss.hasPermi('ruoyi:businessOrder:add')")
    @Log(title = "交易订单信息", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody BusinessOrder businessOrder)
    {
        BusinessOrder result = businessOrderService.insertBusinessOrder(businessOrder);
        return AjaxResult.success("操作成功", result);
//        return toAjax(businessOrderService.insertBusinessOrder(businessOrder));
    }

    /**
     * 修改交易订单信息
     */
    // @PreAuthorize("@ss.hasPermi('ruoyi:businessOrder:edit')")
    @Log(title = "交易订单信息", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody BusinessOrder businessOrder)
    {
        return toAjax(businessOrderService.updateBusinessOrder(businessOrder));
    }

    /**
     * 删除交易订单信息
     */
    // @PreAuthorize("@ss.hasPermi('ruoyi:businessOrder:remove')")
    @Log(title = "交易订单信息", businessType = BusinessType.DELETE)
	@DeleteMapping("/{orderIds}")
    public AjaxResult remove(@PathVariable Long[] orderIds)
    {
        return toAjax(businessOrderService.deleteBusinessOrderByOrderIds(orderIds));
    }

    /**
     * 关闭订单
     * @param orderNo
     * @return
     */
    @GetMapping("/closeOrder/{orderNo}/{platform}")
    public Boolean closeOrder(@PathVariable("orderNo") String orderNo,@PathVariable("platform") String platform){
        Boolean aBoolean = elegentPay.closePay(orderNo,platform);
        return aBoolean;
    }

    /**
     * 退款
     * @param orderNo
     * @return
     */
    @GetMapping("/refund/{orderNo}/{platform}")
    public boolean refund(@PathVariable("orderNo") String orderNo,@PathVariable("platform") String platform){
        RefundRequest refundRequest=new RefundRequest();
        refundRequest.setTotalFee(1);
        refundRequest.setRefundAmount(1);
        refundRequest.setOrderSn(orderNo);
        refundRequest.setRequestNo(System.currentTimeMillis()+"");
        Boolean refund = elegentPay.refund(refundRequest,platform);
        return refund;
    }

    /**
     * 查询订单
     * @param orderNo
     * @return
     */
    @GetMapping("/query/{orderNo}/{platform}")
    public QueryResponse query(@PathVariable("orderNo") String orderNo, @PathVariable("platform") String platform){
        QueryResponse queryResponse = elegentPay.queryTradingOrderNo(orderNo,platform);
        return queryResponse;
    }

    /**
     * 查询退款订单
     * @param orderNo
     * @return
     */
    @GetMapping("/queryRefund/{orderNo}/{platform}")
    public QueryRefundResponse queryRefund(@PathVariable("orderNo") String orderNo, @PathVariable("platform") String platform){
        QueryRefundResponse queryRefundResponse = elegentPay.queryRefundTrading(orderNo,platform);
        return queryRefundResponse;
    }

//    /**
//     * 根据员工id获取交易订单列表
//     */
//    @PreAuthorize("@ss.hasPermi('ruoyi:businessOrder:query')")
//    @GetMapping("/employee/{employeeId}") // 修改路径避免冲突
//    public AjaxResult getByEmployeeId(@PathVariable("employeeId") Long employeeId) {
//        List<BusinessOrder> orders = businessOrderService.selectBusinessOrderByEmployeeId(employeeId);
//        return success(orders);
//    }

    /**
     * 根据员工id和支付状态获取交易订单列表
     */
    // @PreAuthorize("@ss.hasPermi('ruoyi:businessOrder:query')")
    @GetMapping("/employee/payStatus/{employeeId}")
    public AjaxResult getByEmployeeIdAndPayStatus(
        @PathVariable("employeeId") Long employeeId,
        @RequestParam(value = "payStatus", required = false) String payStatus)
    {
        List<BusinessOrder> orders = businessOrderService.selectBusinessOrderByEmployeeIdAndPayStatus(employeeId, payStatus);
        return success(orders);
    }

    /**
     * 根据员工id和订单状态获取交易订单列表
     */
    // @PreAuthorize("@ss.hasPermi('ruoyi:businessOrder:query')")
    @GetMapping("/employee/orderStatus/{employeeId}")
    public AjaxResult getByEmployeeIdAndOrderStatus(
            @PathVariable("employeeId") Long employeeId,
            @RequestParam(value = "orderStatus", required = false) String orderStatus)
    {
        List<BusinessOrder> orders = businessOrderService.selectBusinessOrderByEmployeeIdAndOrderStatus(employeeId, orderStatus);
        return success(orders);
    }


}
